/**
 * Created with JetBrains WebStorm. User: zhouxg Date: 13-7-1 Time: 下午9:07
 */
define('tesla-core', [ 'juicer' ], function(require, exports, module){
	
	var juicer = require("juicer");

	var Tesla = function() {
	};
	
	var $ts = new Tesla();
		var _this = this;

		this.BASH_PATH = "./../../../";
		this.SERVICE_PREFIX = "";
		this.TMPL_PATH = "tpl/";
		this.DEFAULT_CONTAINER_ID = "sys-container";
		this.COMPONENT_PACKAGE = "scm/components/";

		this.load = function(action, param, container, target) {
			require.async(this.resolveScriptUrl(action), function(controller) {
				
				container =  (container || $("#" + _this.DEFAULT_CONTAINER_ID));

				var config = new ConfigHandler(controller, action, param),
					handler = new ActionHandler(config, param, container, target),
					render = function() {
						if (typeof (config.handler) === "undefined") {
							handler.render();
						} else {
							config.handler.call(controller, handler);
						}
					};
					
				
				if (config.service && config.service.length > 0) {
					_this.ajaxJSON(config.service, config.method, handler.param).done(function(result) {
						handler.model = result;
						render();
					});
				} else {
					render();
				}
				
				container.show();
			});
		};

		this.submit = function(action) {
			var _e = getEvent(),
				_form = $(_e.target).parents("form"),
				_data = {};

			if (action.indexOf(".") < 0) {
				action = _form.closest("[data-box]").data("controller") + "." + action;
			}

			var _arr = _form.formToArray();

			for (var i = _arr.length; i--;) {
				var _item = _arr[i];
				if (_item.type === "checkbox") {
					if (!_data[_item.name]) {
						_data[_item.name] = [];
					}
					_data[_item.name].push(_item.value);
				} else {
					_data[_item.name] = _item.value;
				}
			}

			_this.load(action, _data, undefined, _e);
		};

		this.call = function(action, param) {
			var _target = $(getEvent().target);
			if (action.indexOf(".") < 0) {
				action = _target.closest("[data-box]").data("controller") + "." + action;
			}
			this.load(action, param, _target.closest("[data-box]"));
		};

		this.link = function(action, param) {
			var _target = $(getEvent().target);
			if (action.indexOf(".") < 0) {
				action = _target.closest("[data-box]").data("controller") + "." + action;
			}
			this.load(action, param, _target.closest("[data-box]"));
		};

		this.compile = function(html, data) {
			var template = juicer(html, data);
			return $(template);
		};
		
		// -----------------------------ajax请求相关接口----------------------------

		this.ajaxJSON = function(service, type, param) {
			var _def = $.Deferred();

			$.ajax({
				url : this.getServicePath(service),
				data : type.toUpperCase() === "GET" ?  param : JSON.stringify(param),
				dataType : "json",
				type : type,
				contentType : "application/json;charset=UTF-8",
				success : function(result) {
					if (result.returnCode.code === "AAAAAA") {
						_def.resolve(result.reply);
					} else {
						_def.reject(result);
					}
				},
				error : function(result) {
					_def.reject(result);
				},
				cache :false
			});
			return _def.promise();
		};

		this.postJSON = function(service, param) {
			return this.ajaxJSON(service, "POST", param);
		};

		this.getJSON = function(service, param) {
			return this.ajaxJSON(service, "GET", param);
		};
		
		this.putJSON = function(service, param) {
			return this.ajaxJSON(service, "PUT", param);
		};
		
		this.deleteJSON = function(service, param) {
			return this.ajaxJSON(service, "DELETE", param);
		};

		// -----------------------------URL解析等相关接口结束----------------------------
		this.getActionName = function(action) {
			return action.substring(0, action.lastIndexOf("."));
		};

		this.getServicePath = function(service) {
			return this.SERVICE_PREFIX + service;
		};

		this.resolveScriptUrl = function(action) {
			return this.BASH_PATH + this.TMPL_PATH
					+ action.substring(0, action.lastIndexOf(".")).replace(/\./g, "/")
					+ "/controller.js";
		};

		// ----------------------------UI组件相关借口----------------------------------

		this.showInfo = function(msg) {
			require.async(this.COMPONENT_PACKAGE + "sys-alert", function(Alert) {
				Alert.alert("alert-info", "提示信息", msg);
				setTimeout(Alert.close, 3000);
			});
		};

		this.showError = function(msg) {
			require.async(this.COMPONENT_PACKAGE + "sys-alert", function(Alert) {
				Alert.alert("alert-error", "错误信息", msg);
				setTimeout(Alert.close, 3000);
			});
		};
		
		this.pop = function (title, action, param) {
			require.async(this.COMPONENT_PACKAGE + "sys-pop", function(Pop) {
				Pop.pop(title, action, param, _this);
			});
		}
		
		this.close = function(com, data) {
			require.async(this.COMPONENT_PACKAGE + "sys-pop", function(Pop) {
				Pop.close(com, data);
			});
		}
	};

	function ConfigHandler(controller, action, param) {
		var _name = action.substr(action.lastIndexOf(".") + 1);
		var _namespace = action.substring(0, action.lastIndexOf("."));
		var _config = controller.config[_name] || {};
		
		param = $.extend(_config["defaultParam"], param || {});
		
		var _retObj = {
			name : _name,
			namespace : _namespace,
			action : action,
			view : _config["view"] || _name,
			service : resolveServiceStr(_config["service"], param),
			method : _config["method"] || "GET",
			handler : controller[_name],
			param : param
		};
		
		return _retObj;
	}

	function resolveServiceStr(service, param){
		if (!service)
			return service;
		return juicer(service, {param : param});
	}
	
	function ActionHandler(config, param, container, target, $ts) {
		this.param = config.param;
		this.model = {};
		this.view = undefined;
		this.target = target;
		
		var _def = $.Deferred();
		var _this = this;
	}
	
	ActionHandler.prototype = {
			refresh : function() {
				$ts.load(config.action, this.param, this.view);
			};	
			
			this.navigateTo = function(action, param) {
				if (!this.view) {
					this.view = $(this.target).parents("[data-box]");
				}
				
				$ts.load(action.indexOf(".") < 0 ? config.namespace + "." + action : action, param, this.view);
			};
			
			this.render = function(callback) {
				var viewPath = $ts.TMPL_PATH + config.namespace.replace(/\./g, "/") + "/" + config.view + ".html";
				var data = {
					param : this.param,
					model : this.model
				};

				$.ajax(viewPath, {
					success : 	function(result) {
									_this.view = $ts.compile("<div data-box>" + result + "</div>", data);
									_this.view.data("controller", config.namespace);
									
									if (typeof (callback) === "undefined") {
										_this.renderEnd();
									} else {
										callback();
									}
								},
					dataType : "html"
				});
				
				return _def.promise();
			};
			
			this._renderComponent = function() {
				this.view.find("[ts-type]").each(function(index, com) {
					var _types = $(this).attr("ts-type").split(" ");
					
					for (var i = _types.length; i--;) {
						var _type = _types[i];
						require.async($ts.COMPONENT_PACKAGE + _type, function(Component) {
							Component.init($(com), _this.model, _this.param, $ts);
						});
					}
				});
			};
			
			this.renderEnd = function() {
				this._renderComponent();
				container.empty();
				container.append(this.view);
				_def.resolve();
			};
	};
		
		
	function getEvent() {
		if (window.event) {
			return $.event.fix(window.event);
		}
		var f = arguments.callee.caller;
		do {
			var e = f.arguments[0];
			if (e instanceof Event || e instanceof $.Event) {
				return $.event.fix(e);
			}
		} while (f = f.caller);
	}

	module.exports = new Tesla();
});
